package com.kexio.file.controller;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.kexio.common.dto.PageRequest;
import com.kexio.common.dto.PageResponse;
import com.kexio.common.dto.Result;
import com.kexio.dynamic.feature.annotation.FeatureToggle;
// TODO: 企业级功能注解暂时注释，待framework完善后启用
// import com.kexio.enterprise.governance.ratelimit.annotation.RateLimit;
// import com.kexio.enterprise.observability.logging.annotation.OperateLog;
import com.kexio.file.domain.FileInfo;
import com.kexio.file.dto.FileChunk;
import com.kexio.file.dto.FileUploadRequest;
import com.kexio.file.dto.FileUploadResult;
import com.kexio.file.service.FileService;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;

/**
 * 文件管理控制器
 * 
 * @author kexio
 */
@RestController
@RequestMapping("/api/files")
@Tag(name = "文件管理", description = "企业级文件服务API")
public class FileController {

    @Autowired
    private FileService fileService;

    /**
     * 单文件上传
     */
    @Operation(summary = "上传文件", description = "上传单个文件")
    @PostMapping("/upload")
    public ResponseEntity<Result<FileUploadResult>> uploadFile(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "businessType", required = false) String businessType,
            @RequestParam(value = "businessId", required = false) String businessId,
            @RequestParam(value = "userId") Long userId,
            @RequestParam(value = "publicAccess", defaultValue = "false") Boolean publicAccess) {
        
        try {
            FileUploadRequest request = new FileUploadRequest();
            request.setOriginalFilename(file.getOriginalFilename());
            request.setFileSize(file.getSize());
            request.setContentType(file.getContentType());
            request.setBusinessType(businessType);
            request.setBusinessId(businessId);
            request.setUploadUserId(userId);
            request.setPublicAccess(publicAccess);
            
            FileUploadResult result = fileService.uploadFile(request, file.getInputStream());
            return ResponseEntity.ok(Result.success(result));
            
        } catch (IOException e) {
            return ResponseEntity.ok(Result.error("文件上传失败: " + e.getMessage()));
        }
    }

    /**
     * 检查文件是否可以秒传
     */
    @Operation(summary = "检查秒传", description = "根据文件哈希检查是否可以秒传")
    @GetMapping("/check-instant")
    public ResponseEntity<Result<FileInfo>> checkInstantUpload(
            @RequestParam String fileHash,
            @RequestParam Long fileSize) {
        
        FileInfo existingFile = fileService.checkInstantUpload(fileHash, fileSize);
        if (existingFile != null) {
            return ResponseEntity.ok(Result.success(existingFile));
        } else {
            return ResponseEntity.ok(Result.success(null));
        }
    }

    /**
     * 执行文件秒传
     */
    @Operation(summary = "文件秒传", description = "基于已存在文件执行秒传")
    @PostMapping("/instant-upload")
    public ResponseEntity<Result<FileUploadResult>> instantUpload(
            @RequestBody FileUploadRequest request,
            @RequestParam Long existingFileId) {
        
        FileUploadResult result = fileService.instantUpload(request, existingFileId);
        return ResponseEntity.ok(Result.success(result));
    }

    /**
     * 初始化分片上传
     */
    @Operation(summary = "初始化分片上传", description = "初始化大文件分片上传")
    @FeatureToggle(value = "chunk_upload", description = "分片上传功能")
    @PostMapping("/chunk/init")
    public ResponseEntity<Result<String>> initChunkUpload(@RequestBody FileUploadRequest request) {
        String uploadId = fileService.initChunkUpload(request);
        return ResponseEntity.ok(Result.success(uploadId));
    }

    /**
     * 上传文件分片
     */
    @Operation(summary = "上传文件分片", description = "上传单个文件分片")
    @PostMapping("/chunk/upload")
    public ResponseEntity<Result<String>> uploadChunk(
            @RequestParam String uploadId,
            @RequestParam int chunkNumber,
            @RequestParam int totalChunks,
            @RequestParam("chunk") MultipartFile chunkFile) {
        
        try {
            FileChunk chunk = new FileChunk();
            chunk.setChunkNumber(chunkNumber);
            chunk.setTotalChunks(totalChunks);
            chunk.setChunkSize(chunkFile.getSize());
            chunk.setInputStream(chunkFile.getInputStream());
            
            String chunkId = fileService.uploadChunk(uploadId, chunk);
            return ResponseEntity.ok(Result.success(chunkId));
            
        } catch (IOException e) {
            return ResponseEntity.ok(Result.error("分片上传失败: " + e.getMessage()));
        }
    }

    /**
     * 合并文件分片
     */
    @Operation(summary = "合并文件分片", description = "合并所有分片完成上传")
    @PostMapping("/chunk/merge")
    public ResponseEntity<Result<FileUploadResult>> mergeChunks(
            @RequestParam String uploadId,
            @RequestBody List<String> chunkIds) {
        
        FileUploadResult result = fileService.mergeChunks(uploadId, chunkIds, null);
        return ResponseEntity.ok(Result.success(result));
    }

    /**
     * 取消分片上传
     */
    @Operation(summary = "取消分片上传", description = "取消分片上传并清理临时文件")
    @DeleteMapping("/chunk/abort")
    public ResponseEntity<Result<Boolean>> abortChunkUpload(@RequestParam String uploadId) {
        boolean success = fileService.abortChunkUpload(uploadId);
        return ResponseEntity.ok(Result.success(success));
    }

    /**
     * 下载文件
     */
    @Operation(summary = "下载文件", description = "根据文件ID下载文件")
    @GetMapping("/download/{fileId}")
    public void downloadFile(
            @Parameter(description = "文件ID", required = true) @PathVariable Long fileId,
            @RequestParam Long userId,
            HttpServletResponse response) {
        
        try {
            FileInfo fileInfo = fileService.getFileById(fileId);
            if (fileInfo == null) {
                response.setStatus(404);
                return;
            }
            
            InputStream inputStream = fileService.downloadFile(fileId, userId);
            
            // 设置响应头
            response.setContentType(fileInfo.getContentType() != null ? 
                fileInfo.getContentType() : MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, 
                "attachment; filename=\"" + fileInfo.getOriginalFilename() + "\"");
            response.setContentLengthLong(fileInfo.getFileSize());
            
            // 写入响应流
            inputStream.transferTo(response.getOutputStream());
            response.getOutputStream().flush();
            
        } catch (IOException e) {
            response.setStatus(500);
        }
    }

    /**
     * 获取文件访问URL
     */
    @Operation(summary = "获取文件访问URL", description = "获取文件的临时访问URL")
    @GetMapping("/access-url/{fileId}")
    public ResponseEntity<Result<String>> getFileAccessUrl(
            @Parameter(description = "文件ID", required = true) @PathVariable Long fileId,
            @RequestParam Long userId,
            @RequestParam(defaultValue = "3600") int expireSeconds) {
        
        String accessUrl = fileService.getFileAccessUrl(fileId, userId, expireSeconds);
        return ResponseEntity.ok(Result.success(accessUrl));
    }

    /**
     * 删除文件
     */
    @Operation(summary = "删除文件", description = "软删除指定文件")
    @DeleteMapping("/{fileId}")
    public ResponseEntity<Result<Boolean>> deleteFile(
            @Parameter(description = "文件ID", required = true) @PathVariable Long fileId,
            @RequestParam Long userId) {
        
        boolean success = fileService.deleteFile(fileId, userId);
        return ResponseEntity.ok(Result.success(success));
    }

    /**
     * 批量删除文件
     */
    @Operation(summary = "批量删除文件", description = "批量软删除文件")
    @DeleteMapping("/batch")
    public ResponseEntity<Result<Integer>> batchDeleteFiles(
            @RequestBody List<Long> fileIds,
            @RequestParam Long userId) {
        
        int deletedCount = fileService.batchDeleteFiles(fileIds, userId);
        return ResponseEntity.ok(Result.success(deletedCount));
    }

    /**
     * 获取文件信息
     */
    @Operation(summary = "获取文件信息", description = "根据文件ID获取详细信息")
    @GetMapping("/{fileId}")
    public ResponseEntity<Result<FileInfo>> getFileInfo(
            @Parameter(description = "文件ID", required = true) @PathVariable Long fileId) {
        
        FileInfo fileInfo = fileService.getFileById(fileId);
        if (fileInfo == null) {
            return ResponseEntity.ok(Result.error("文件不存在"));
        }
        return ResponseEntity.ok(Result.success(fileInfo));
    }

    /**
     * 分页查询文件
     */
    @Operation(summary = "分页查询文件", description = "根据条件分页查询文件列表")
    @GetMapping("/page")
    public ResponseEntity<Result<PageResponse<FileInfo>>> queryFiles(
            @RequestParam(required = false) String businessType,
            @RequestParam(required = false) String businessId,
            @RequestParam(required = false) Long userId,
            PageRequest pageRequest) {
        
        PageResponse<FileInfo> result = fileService.queryFiles(businessType, businessId, userId, pageRequest);
        return ResponseEntity.ok(Result.success(result));
    }

    /**
     * 复制文件
     */
    @Operation(summary = "复制文件", description = "复制已存在的文件")
    @PostMapping("/copy/{sourceFileId}")
    public ResponseEntity<Result<FileUploadResult>> copyFile(
            @Parameter(description = "源文件ID", required = true) @PathVariable Long sourceFileId,
            @RequestBody FileUploadRequest targetRequest,
            @RequestParam Long userId) {
        
        FileUploadResult result = fileService.copyFile(sourceFileId, targetRequest, userId);
        return ResponseEntity.ok(Result.success(result));
    }

    /**
     * 文件预览
     */
    @Operation(summary = "文件预览", description = "获取文件预览URL")
    @GetMapping("/preview/{fileId}")
    public ResponseEntity<Result<String>> previewFile(
            @Parameter(description = "文件ID", required = true) @PathVariable Long fileId,
            @RequestParam Long userId) {
        
        String previewUrl = fileService.generatePreviewUrl(fileId, userId);
        return ResponseEntity.ok(Result.success(previewUrl));
    }

    /**
     * 获取文件统计信息
     */
    @Operation(summary = "文件统计", description = "获取文件统计信息")
    @GetMapping("/statistics")
    public ResponseEntity<Result<FileService.FileStatistics>> getFileStatistics(
            @RequestParam(required = false) String businessType,
            @RequestParam(required = false) Long userId) {
        
        FileService.FileStatistics stats = fileService.getFileStatistics(businessType, userId);
        return ResponseEntity.ok(Result.success(stats));
    }
}
